home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- * Alternative ST symbol table lister.
- */
-
- /* highly munged from above, VERY quick and dirty nm, just enough
- here to find _stksize for fixstk.c and printstk.c, may be
- useful for other stuff.
-
- WARNING: -g option will not work with gcc-ld produced a.out
-
-
- ++jrb
- */
- /*
- * Modified to handle expanded, GST linker derived, format for symbols.
- * This format is produced with -G flag to a proper version of gcc-ld.
- * -g flag also will work if ld coached properly.
- *
- * --mj
- */
-
- /*
- * ++jrb rework and cleanup while adding A_TFILE A_TFARC
- */
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #ifdef CROSSATARI
- #include "cross-inc/compiler.h"
- #include "cross-inc/st-out.h"
- #else
- #include <compiler.h>
- #include <st-out.h>
- #endif
-
- #ifdef BYTE_SWAP
- #define SWAP4(y) (((unsigned)(y)>>24) + (((unsigned)(y)>>8)&0xff00) + \
- (((unsigned)(y)<<8)&0xff0000) + ((unsigned)(y)<<24))
- #define SWAP2(y) ((((unsigned)(y)&0xff00)>>8) + (((unsigned)(y)&0x00ff)<<8))
- #endif /* BYTE_SWAP */
-
- #ifndef WORD_ALIGNED
- # define SIZEOF_SYM ((size_t)sizeof(struct asym))
- #else
- # define SIZEOF_SYM ((size_t)14)
- #endif
-
- #ifdef atarist
- #define READB "rb"
- #else
- #define READB "r"
- #endif
-
- struct xsym {
- char name[8];
- union {
- unsigned char _flags[2];
- unsigned short _sflgs;
- } u;
- unsigned long value;
- char tail[SIZEOF_SYM];
- };
-
- #define flags u._flags[0]
- #define xflags u._flags[1]
- #define sflgs u._sflgs
-
- #ifdef __STDC__
- # define P(s) s
- #else
- # define P(s) ()
- #endif
-
- int main P((int argc , char **argv ));
- int cmp P((struct xsym *s1 , struct xsym *s2 ));
- int doname P((char *s , int many ));
- long dohdr P((FILE *fd ));
- void dosym P((struct xsym *s ));
- int not_glob P((unsigned int x ));
- void sflags P((struct xsym *s ));
- void ckfread P((void *buf , int siz , int n , FILE *fp ));
- long readhead P((struct aexec *h , int n , FILE *fd ));
- int readsyms P((struct xsym *syms , int n , FILE *fd ));
- void usage P((void ));
-
- #undef P
-
- extern void dump_version(char *prog);
- char *progname = "cnm";
-
- int gflag;
- int uflag;
-
- int main(argc, argv)
- int argc;
- char **argv;
- {
- int c, status = 0;
- extern char *optarg;
- extern int optind;
-
- if (argv[0][0] != '\0')
- progname = argv[0];
-
- while ((c = getopt(argc, argv, "guv")) != -1)
- switch (c)
- {
- case 'g':
- gflag = 1;
- break;
- case 'u':
- uflag = 1;
- break;
- case 'v' :
- dump_version(progname);
- exit(0);
- break;
- case '?':
- usage();
- }
- c = argc - optind;
- if(c <= 0)
- usage();
-
- for (; optind < argc; optind++)
- status |= doname(argv[optind], (c > 1));
- return status;
- }
-
- int cmp(s1, s2)
- struct xsym *s1, *s2;
- {
- long diff = s1->value - s2->value;
- return (diff > 0) - (diff < 0);
- }
-
- int doname(s, many)
- char *s;
- int many;
- {
- FILE *fd, *fopen();
- long i, count;
-
- if(!(fd = fopen(s, READB)))
- {
- perror(s);
- return 2;
- }
- if (many)
- printf("\n%s:\n", s);
-
- if (i = dohdr(fd))
- {
- struct xsym *syms, *savesyms;
- struct xsym *currsym;
- printf("%ld slots mem %ld\n", i, (long)(i*sizeof(struct xsym)));
-
- if((savesyms = syms = (struct xsym *)malloc(i*sizeof(struct xsym))) == NULL)
- {
- perror("Outa mem");
- exit(4);
- }
- count = i;
- currsym = syms;
- while (count)
- {
- if(readsyms(currsym, 1, fd) != 1)
- {
- perror("reading syms");
- exit(8);
- }
- if (--count)
- {
- if (A_LNAM == (currsym->xflags & A_LNAM))
- {
- if(fread(currsym->tail, SIZEOF_SYM, 1, fd) != 1)
- {
- perror("reading syms");
- exit(16);
- }
- --i;
- --count;
- }
- }
- else /* object was partially stripped */
- currsym->xflags &= ~A_LNAM;
- if (gflag && not_glob((unsigned int)(currsym->flags)))
- --i;
- else
- currsym++;
- }
- fclose(fd);
- printf("%ld %s symbol(s)\n", i, (gflag ? "global ": ""));
- if (!uflag)
- qsort(syms, i, sizeof(struct xsym), cmp);
- while (i--)
- {
- dosym(syms);
- syms += 1;
- }
- free(savesyms);
- }
- return 0;
- }
-
- long dohdr(fd)
- FILE *fd;
- {
- struct aexec h;
- long i;
-
- i = readhead(&h, 1, fd);
- if (i != 1 || h.a_magic != CMAGIC)
- {
- fprintf(stderr, "Bad header\n");
- return 0L;
- }
- fseek(fd, (h.a_text + h.a_data), 1);
- return h.a_syms / SIZEOF_SYM;
- }
-
- void
- dosym(s)
- struct xsym *s;
- {
- printf("%-8.8s", s->name);
- printf("%-14.14s", (A_LNAM == (s->xflags & A_LNAM) ? s->tail : ""));
- printf("\t%8lx ", s->value);
- s->xflags &= ~A_LNAM;
- sflags(s);
- putchar('\n');
- }
-
- char *fname[] = {
- "?0?", " bss", " text", "?3?", " data",
- "?5?", "?6?", "?7?"
- };
- char *Fname[] = {
- "?0?", "Bss", "Text", "?3?", "Data",
- "?5?", "?6?", "?7?"
- };
-
- int not_glob(x)
- unsigned int x;
- {
- x &= 0xff;
- if (x & 0x20)
- return 0;
- x &= ~0x20;
- if (x == 0x88)
- return 0;
- return 1;
- }
-
- void
- sflags(s)
- struct xsym *s;
- {
- unsigned int x = s->flags;
- char **category;
- int lflag;
-
- if(s->sflgs == A_TFILE)
- printf("text file");
- else if (s->sflgs == A_TFARC)
- printf("text file archive");
- else
- {
- if (0 != (lflag = not_glob(x)))
- category = fname;
- else
- category = Fname;
-
- x &= 0xff;
- if (x & 0x20)
- printf("global ");
- x &= ~0x20;
- if (x & 0xd8)
- {
- if (x & 0x08)
- printf (" external");
- if (x & 0x50)
- {
- printf (" equ");
- if (x & 0x10)
- printf (" reg");
- }
- if (x & 0x80)
- printf (" abs");
- if (!lflag)
- printf(" G");
- }
- else
- {
- x &= 7;
- printf(category[x]);
- }
- }
- printf(" (0x%04x)",(unsigned int)(s->sflgs));
- }
-
- void ckfread(buf, siz, n, fp)
- void *buf;
- int siz, n;
- FILE *fp;
- {
- if(fread(buf, siz, n, fp) != n)
- {
- perror("reading");
- exit(32);
- }
- }
-
- long readhead(h, n, fd)
- struct aexec *h;
- int n;
- FILE *fd;
- {
- short i;
- long j;
- int k;
-
- for(k = 0; k < n; k++)
- {
- ckfread(&i, 2, 1, fd);
- h->a_magic = i;
- ckfread(&j, 4, 1, fd);
- h->a_text = j;
- ckfread(&j, 4, 1, fd);
- h->a_data = j;
- ckfread(&j, 4, 1, fd);
- h->a_bss = j;
- ckfread(&j, 4, 1, fd);
- h->a_syms = j;
- ckfread(&j, 4, 1, fd);
- h->a_AZero1 = j;
- ckfread(&j, 4, 1, fd);
- h->a_ldflgs = j;
- ckfread(&i, 2, 1, fd);
- h->a_isreloc = i;
- }
- #ifdef BYTE_SWAP
- h->a_magic = SWAP2(h->a_magic);
- h->a_text = SWAP4(h->a_text);
- h->a_data = SWAP4(h->a_data);
- h->a_bss = SWAP4(h->a_bss);
- h->a_syms = SWAP4(h->a_syms);
- h->a_AZero1 = SWAP4(h->a_AZero1);;
- h->a_ldflgs = SWAP4(h->a_ldflgs);;
- h->a_isreloc = SWAP2(h->a_isreloc);;
- #endif
- return k;
- }
-
- int readsyms(syms, n, fd)
- struct xsym *syms;
- int n;
- FILE *fd;
- {
- int k;
-
- for(k = 0; k < n; k++, syms++)
- {
- ckfread(syms->name, 8, 1, fd);
- ckfread(&(syms->sflgs), 2, 1, fd);
- ckfread(&(syms->value), 4, 1, fd);
- #ifdef BYTE_SWAP
- /*
- syms->sflgs = SWAP2(syms->sflgs);
- */
- syms->value = SWAP4(syms->value);
- #endif
-
- }
- return k;
- }
-
- void usage()
- {
- dump_version(progname);
- fprintf(stderr, "cnm [-g] files...\n");
- exit(1);
- }
-
- #if !defined(__GNUC__) && defined(hpux)
-
- char *xmalloc(n)
- int n; /* sigh! */
- {
- char *ret = (char *)malloc(n);
-
- if(ret) return ret;
- perror("malloc");
- exit(1);
- }
-
- char *xrealloc(b, n)
- char * b;
- int n; /* sigh! */
- {
- char *ret = (char *)realloc(b, n);
-
- if(ret) return ret;
- perror("realloc");
- exit(2);
- }
- #endif
-